package com.easy.cloud.web.service.upms.biz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.easy.cloud.web.component.core.constants.GlobalCommonConstants;
import com.easy.cloud.web.component.core.exception.BusinessException;
import com.easy.cloud.web.component.core.util.BeanUtils;
import com.easy.cloud.web.component.mysql.query.SpecificationWrapper;
import com.easy.cloud.web.service.upms.api.dto.RoleDTO;
import com.easy.cloud.web.service.upms.api.dto.RoleQueryDTO;
import com.easy.cloud.web.service.upms.api.vo.RoleVO;
import com.easy.cloud.web.service.upms.biz.constant.UpmsCacheConstants;
import com.easy.cloud.web.service.upms.biz.converter.RoleConverter;
import com.easy.cloud.web.service.upms.biz.domain.MenuDO;
import com.easy.cloud.web.service.upms.biz.domain.RoleDO;
import com.easy.cloud.web.service.upms.biz.repository.MenuRepository;
import com.easy.cloud.web.service.upms.biz.repository.RoleRepository;
import com.easy.cloud.web.service.upms.biz.service.IRoleService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Role 业务逻辑
 *
 * @author Fast Java
 * @date 2023-08-03 14:32:52
 */
@Slf4j
@Service
@AllArgsConstructor
public class RoleServiceImpl implements IRoleService {

    private final RoleRepository roleRepository;

    private final MenuRepository menuRepository;

    /**
     * 构建橘色菜单信息
     *
     * @param roleDTO 角色入参信息
     */
    private void buildRoleBeforeStore(RoleDTO roleDTO, RoleDO roleDO) {
        // 根据角色名称和编码获取角色信息
        List<RoleDO> roles = roleRepository.findByNameOrCode(roleDTO.getName(), roleDTO.getCode());
        // ID不为空
        if (StrUtil.isNotBlank(roleDTO.getId())) {
            roles.stream().filter(role -> !role.getId().equals(roleDTO.getId()))
                    .findFirst().orElseThrow(() -> new BusinessException("当前角色名称或编码已存在"));
        } else if (CollUtil.isNotEmpty(roles)) {
            // ID为空，角色信息不为空，则表示重复
            throw new BusinessException("当前角色名称或编码已存在");
        }

        // 菜单ID不为空
        if (CollUtil.isNotEmpty(roleDTO.getMenuIds())) {
            List<MenuDO> roleMenus = menuRepository.findAllById(roleDTO.getMenuIds());
            roleDO.setMenus(roleMenus);
        }
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    public RoleVO save(RoleDTO roleDTO) {
        // 转换成DO对象
        RoleDO role = RoleConverter.convertTo(roleDTO);
        // 构建菜单数据
        this.buildRoleBeforeStore(roleDTO, role);
        // 存储
        roleRepository.save(role);
        // 转换对象
        return RoleConverter.convertTo(role);
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    @CacheEvict(value = UpmsCacheConstants.SUPER_ROLE_DETAILS, allEntries = true)
    public RoleVO update(RoleDTO roleDTO) {
        // 转换成DO对象
        if (Objects.isNull(roleDTO.getId())) {
            throw new RuntimeException("当前更新对象ID为空");
        }

        // TODO 业务逻辑校验
        RoleDO role = roleRepository.findById(roleDTO.getId())
                .orElseThrow(() -> new BusinessException("当前菜单信息不存在"));
        // 将修改的数据赋值给数据库数据
        BeanUtils.copyProperties(roleDTO, role, true);
        // 构建菜单数据
        this.buildRoleBeforeStore(roleDTO, role);
        // 更新
        roleRepository.save(role);
        // 转换对象
        return RoleConverter.convertTo(role);
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    @CacheEvict(value = UpmsCacheConstants.SUPER_ROLE_DETAILS, allEntries = true)
    public Boolean removeById(String roleId) {
        // TODO 业务逻辑校验
        // 逻辑删除操作
        roleRepository.logicDelete(roleId);
        return true;
    }

    @Override
    public RoleVO detailById(String roleId) {
        // 删除
        RoleDO role = roleRepository.findById(roleId)
                .orElseThrow(() -> new RuntimeException("当前数据不存在"));
        // 转换
        RoleVO roleVO = RoleConverter.convertTo(role);
        // 获取对应的惨菜单信息
        roleVO.setMenuIds(role.getMenus().stream().map(MenuDO::getId).collect(Collectors.toSet()));
        return roleVO;
    }

    @Override
    public List<RoleVO> list(RoleQueryDTO roleQueryDTO) {
        // 获取列表数据
        List<RoleDO> roles = roleRepository.findAll(SpecificationWrapper.where()
                .ne(RoleDO::getCode, GlobalCommonConstants.SUPER_ADMIN_ROLE)
                .eq(StrUtil.isNotBlank(roleQueryDTO.getCode()), RoleDO::getCode, roleQueryDTO.getCode())
                .like(StrUtil.isNotBlank(roleQueryDTO.getName()), RoleDO::getName, roleQueryDTO.getName()));
        return RoleConverter.convertTo(roles);
    }

    @Override
    public List<RoleVO> findAllByCodes(List<String> roleCodes) {
        return roleRepository.findAllByCodeIn(roleCodes)
                .stream()
                .map(RoleConverter::convertTo)
                .collect(Collectors.toList());
    }

    @Override
    public Page<RoleVO> page(RoleQueryDTO roleQueryDTO) {
        // 构建分页数据
        return RoleConverter.convertTo(roleRepository.findAll(
                SpecificationWrapper.where()
                        .ne(RoleDO::getCode, GlobalCommonConstants.SUPER_ADMIN_ROLE)
                        .eq(StrUtil.isNotBlank(roleQueryDTO.getCode()), RoleDO::getCode, roleQueryDTO.getCode())
                        .like(StrUtil.isNotBlank(roleQueryDTO.getName()), RoleDO::getName, roleQueryDTO.getName()),
                roleQueryDTO.pageable()));
    }
}